package com.zzl.study.sharding.customer;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zzl.study.sharding.ShardingJdbcDemoApp;
import com.zzl.study.sharding.domain.Book;
import com.zzl.study.sharding.mapper.BookMapper;
import org.apache.shardingsphere.infra.hint.HintManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Random;

/**
 * @author: zhangzl
 * @date: 2022/7/17 13:25
 * @version: 1.0
 * @description: 自定义类分片算法测试类
 * spring.profiles.active: hintinline
 */
@SpringBootTest(classes = ShardingJdbcDemoApp.class)
@RunWith(SpringRunner.class)
public class CustomerShardingAlgorithm {

    /**
     * 书架区域数组
     */
    private static final String[] REGION_ARRAY = {"A区", "B区", "C区"};

    /**
     * 书架区域数组
     */
    private static final String[] MULTIPLE_REGION_ARRAY = {"A区", "B区", "C区", "D区", "E区", "F区"};

    @Autowired
    private BookMapper bookMapper;

    /**
     * 生成随机价格
     *
     * @return 价格
     */
    private Integer randomPrice() {
        Random random = new Random();
        return Math.abs(random.nextInt(1000));
    }

    /**
     * 测试插入书本表：基于STANDARD策略的范围分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookRangeStandardShardingAlgorithm
     */
    @Test
    public void testInsertBookWithRangeStandardShardingAlgorithm() {
        for (int i = 0; i < 60; i++) {
            Book book = new Book();
            book.setBookName("书本" + i);
            book.setAdminId(Long.parseLong(String.valueOf(i)));
            book.setPrice(randomPrice());
            book.setRegion(REGION_ARRAY[i % REGION_ARRAY.length]);
            bookMapper.insert(book);
            System.out.println(book);
        }
    }

    /**
     * 测试范围查询书本表：基于STANDARD策略的范围分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookRangeStandardShardingAlgorithm
     */
    @Test
    public void testBetweenSelectBookWithRangeStandardShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("price", 300, 500);
        List<Book> books = bookMapper.selectList(queryWrapper);// 通过
        for (Book book : books) {
            System.out.println(book);
        }
    }

    /**
     * 测试插入书本表：基于STANDARD策略的行表达式分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookInlineStandardShardingAlgorithm
     */
    @Test
    public void testInsertBookWithInlineStandardShardingAlgorithm() {
        for (int i = 0; i < 60; i++) {
            Book book = new Book();
            book.setBookName("书本" + i);
            book.setAdminId(Long.parseLong(String.valueOf(i)));
            book.setPrice(randomPrice());
            book.setRegion(REGION_ARRAY[i % REGION_ARRAY.length]);
            bookMapper.insert(book);
            System.out.println(book);
        }
    }

    /**
     * 测试等值查询书本表：基于STANDARD策略的行表达式分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookInlineStandardShardingAlgorithm
     */
    @Test
    public void testEqSelectBookWithInlineStandardShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("admin_id", 35L);
        List<Book> books = bookMapper.selectList(queryWrapper);// 通过
        for (Book book : books) {
            System.out.println(book);
        }
    }

    /**
     * 测试IN查询书本表：基于STANDARD策略的行表达式分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookInlineStandardShardingAlgorithm
     */
    @Test
    public void testInSelectBookWithInlineStandardShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("admin_id", 35L, 56L);
        List<Book> books = bookMapper.selectList(queryWrapper);// 通过
        for (Book book : books) {
            System.out.println(book);
        }
    }

    /**
     * 测试范围查询书本表：基于STANDARD策略的行表达式分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.standard.BookInlineStandardShardingAlgorithm
     */
    @Test
    public void testBetweenSelectBookWithInlineStandardShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("admin_id", 300, 500);
        List<Book> books = bookMapper.selectList(queryWrapper);// 报错
        for (Book book : books) {
            System.out.println(book);
        }
    }

    /**
     * 测试插入书本表：基于COMPLEX策略的复合键分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.complex.BookComplexKeyShardingAlgorithm
     */
    @Test
    public void testInsertBookWithComplexKeyShardingAlgorithm() {
        for (int i = 0; i < 60; i++) {
            Book book = new Book();
            book.setBookName("书本" + i);
            book.setAdminId(Long.parseLong(String.valueOf(i)));
            book.setPrice(randomPrice());
            book.setRegion(REGION_ARRAY[i % REGION_ARRAY.length]);
            bookMapper.insert(book);
            System.out.println(book);
        }
    }

    /**
     * 测试精准查询书本表：基于COMPLEX策略的复合键分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.complex.BookComplexKeyShardingAlgorithm
     */
    @Test
    public void testSelectBookWithComplexKeyShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("region", "B区");
        queryWrapper.in("admin_id", 25L, 40L);
        List<Book> books = bookMapper.selectList(queryWrapper);// 通过
        for (Book book : books) {
            System.out.println(book);
        }
    }

    /**
     * 测试插入书本表：基于HINT策略的精准值分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.hint.BookHintShardingAlgorithm
     */
    @Test
    public void testInsertBookWithHintShardingAlgorithm() {
        for (int i = 0; i < 60; i++) {
            Book book = new Book();
            book.setBookName("书本" + i);
            book.setAdminId(Long.parseLong(String.valueOf(i)));
            book.setPrice(randomPrice());
            String region = MULTIPLE_REGION_ARRAY[i % MULTIPLE_REGION_ARRAY.length];
            book.setRegion(region);
            HintManager hintManager = HintManager.getInstance();
            hintManager.addTableShardingValue("t_book", region);
            bookMapper.insert(book);
            System.out.println(book);
            hintManager.close();
        }
    }

    /**
     * 测试精准查询书本表：基于HINT策略的精准值分片算法
     *
     * @see: com.zzl.study.sharding.algorithm.hint.BookHintShardingAlgorithm
     */
    @Test
    public void testSelectBookWithHintShardingAlgorithm() {
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", 1549666265876930562L);
        HintManager hintManager = HintManager.getInstance();
        hintManager.addTableShardingValue("t_book", "B区");
        List<Book> books = bookMapper.selectList(queryWrapper);// 通过
        for (Book book : books) {
            System.out.println(book);
        }
        hintManager.close();
    }

}
